namespace EnergyGeneratorSimVisualizer.ViewModels
{
    using System;
    using System.ComponentModel;
    using System.Linq.Expressions;
    using System.Reflection;

    public class ViewModelBase : INotifyPropertyChanged
    {
        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Notifies the property changed.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        internal void NotifyPropertyChangedInternal(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }

    public static class ViewModelBaseExtensions
    {
        public static void NotifyPropertyChanged<T>(this T viewModel, Expression<Func<T, object>> propertyExpression)
            where T : ViewModelBase
        {
            string propertyName = string.Empty;

            if (propertyExpression.Body.NodeType == ExpressionType.Convert)
            {
                UnaryExpression e = (UnaryExpression)propertyExpression.Body;

                if (e.Operand.NodeType == ExpressionType.MemberAccess)
                {
                    propertyName = GetMemberName(propertyName, e.Operand);
                }
            }
            else if (propertyExpression.Body.NodeType == ExpressionType.MemberAccess)
            {
                propertyName = GetMemberName(propertyName, propertyExpression.Body);
            }

            if (string.IsNullOrEmpty(propertyName))
            {
                throw new ArgumentException("The expression is no property expression! " + propertyExpression.ToString());
            }

            viewModel.NotifyPropertyChangedInternal(propertyName);
        }

        private static string GetMemberName(string propertyName, Expression e)
        {
            MemberExpression e1 = (MemberExpression)e;

            if (e1.Member.MemberType == MemberTypes.Property)
            {
                propertyName = e1.Member.Name;
            }
            return propertyName;
        }
    }
}
